Raspberry Piで最小サイズのバックアップを作成する
1 はじめに
Raspberry PiのSDカードを複製(バックアップ・リストア)するとき、下記の問題を感じることがあります。
- 16Gとかのカードに入っていると、バックアップイメージ自体が大きいのでコピーに時間がかかる
- バックアップイメージが大きくて場所を取る
- 同一メーカーの同サイズのSDにリストアしようとしてもブロック数の僅かな違いで失敗することがある
今回は、この問題を避けるために、SDカードのイメージを小さくバックアップする方法をまとめてみました。
便利なツールもあると思うのですが、私自身の勉強の兼ねて、すべての操作をコマンドラインで行っています。ddコマンドなど指定を誤るとシステムを壊わしてしまう恐れがありますので、もし、この記事を参考に作業される場合は、充分にご注意下さい。
2 パーティションの自動拡張
ダウンロードしたRASPBIANのイメージをSDカードにコピーして使用すると、初回起動時に、SDカードで利用可能な最大サイズまで自動的にパーティションが拡張されます。
下記は、ダウンロードしたイメージをSDカード(16G)にddでコピーした直後の状態です。 最後のセクタは、9322496であり、9322496 * 512 = 4773117952(4.44G)となっています。
$ sudo fdisk /dev/disk1 Disk: /dev/disk1 geometry: 1923/255/63 [30898176 sectors] #: id cyl hd sec - cyl hd sec [ start - size] ------------------------------------------------------------------------ 1: 0C 0 130 3 - 6 4 22 [ 8192 - 88472] Win95 FAT32L 2: 83 6 30 25 - 586 106 32 [ 98304 - 9322496] Linux files*
そして、このSDカードでRaspberry Piで起動すると、パーティションの状態は下記のように変化します。最後のセクタが30799872となっており、30799872 * 512 = 4773117952(14.68G)まで広がっていることが分かります。
$ sudo fdisk /dev/disk1 Disk: /dev/disk1 geometry: 1923/255/63 [30898176 sectors] #: id cyl hd sec - cyl hd sec [ start - size] ------------------------------------------------------------------------ 1: 0C 0 130 3 - 6 4 22 [ 8192 - 88472] Win95 FAT32L 2: 83 6 30 25 - 1023 254 63 [ 98304 - 30799872] Linux files*
RASPBIANのイメージを確認すると、起動時にパーティションを拡大しているS01resize2fs_onceが確認できます。そして、初回実行されると、このシェルは削除されているので、起動後はこれを見ることができません。
$ hdiutil mount 2018-06-27-raspbian-stretch.img 【RASPBIANのイメージをマウント(/dev/disk2にマウントされた)】 $ mkdir /tmp/Linux $ ext4fuse /dev/disk2s2 /tmp/Linux【ファイルシステムにマウント】 $ cat /tmp/Linux/etc/rc3.d/S01resize2fs_once【S01resize2fs_onceの内容を確認する】 #!/bin/sh ### BEGIN INIT INFO # Provides: resize2fs_once # Required-Start: # Required-Stop: # Default-Start: 3 # Default-Stop: # Short-Description: Resize the root filesystem to fill partition # Description: ### END INIT INFO . /lib/lsb/init-functions case "$1" in start) log_daemon_msg "Starting resize2fs_once" ROOT_DEV=$(findmnt / -o source -n) && resize2fs $ROOT_DEV && update-rc.d resize2fs_once remove && rm /etc/init.d/resize2fs_once && log_end_msg $? ;; *) echo "Usage: $0 start" >&2 exit 3 ;; esac
3 システムの縮小
サイズの小さなバックアップを作成するためには、以下の手順が必要です。
- ファイルシステムの縮小
- パーティションの縮小
なお、この作業は、別のRasbianが起動していところに、対象のSDカードをUSB接続して、Macからsshで接続して行いました。
(1) ファイルシステムの縮小
USBに接続されたSDカードは、 /dev/sda(4.3/15G使用中)として認識されています。 bootパーティションと(/dev/sda1)とrootパティション(/dev/sda2)の2つがありますが、縮小の対象は、/dev/sda2です。
pi@raspberrypi:~ $ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 15G 4.3G 9.3G 32% / ・・・略・・・ /dev/sda1 43M 22M 21M 51% /media/pi/boot /dev/sda2 15G 4.0G 9.8G 29% /media/pi/rootfs
resize2fsで -P オプションをつけると、必要サイズの確認ができます。
pi@raspberrypi:~ $ sudo resize2fs -P /dev/sda2 resize2fs 1.43.4 (31-Jan-2017) Estimated minimum size of the filesystem: 1595822
ここで表示されている1595822の単位はブロック(4Kbyte)なので、1595822 * 4 * 1024 = 6536486912 (6.08Gbyte)となります。
縮小後のサイズは、必要サイズより25400(100Mbyte)ほど多い目にとって、1595822 + 25400 = 1621222 を指定することにしました。
pi@raspberrypi:~ $ umount /dev/sda2 pi@raspberrypi:~ $ sudo e2fsck -f /dev/sda2 pi@raspberrypi:~ $ sudo resize2fs -p /dev/sda2 1621222
(2) パーティションの縮小
現在の状態は、以下のようになっています。2つ目のパーティションは、Startが98304でEndが30898175で14.7G確保されています。
$ sudo fdisk /dev/sda Command (m for help): p ・・・略・・・ Device Boot Start End Sectors Size Id Type /dev/sda1 8192 96663 88472 43.2M c W95 FAT32 (LBA) /dev/sda2 98304 30898175 30799872 14.7G 83 Linux
先程の縮小作業でサイズを1621222 としましたが、こちらは単位がブロック(4Kバイト)で、今度は、セクタ(512バイト)で指定するので 1621222 * 8 = 12969776 セクタ以上確保すれば良いことになります。(ここでは、12970000としておきます)
Startは変えることが出来ないので98304、そしてEndは、98304 + 12970000 で 13068304に変更します。
Command (m for help): d 【 一旦、パーティションを削除します】 Partition number (1,2, default 2): 【パーティション番号は2を指定】 Partition 2 has been deleted. Command (m for help): n 【改めて、パーティションを作成します】 Partition type p primary (1 primary, 0 extended, 3 free) e extended (container for logical partitions) Select (default p): 【プライマリーを選択】 Using default response p. Partition number (2-4, default 2):2【パーティション番号は2を指定】 First sector (2048-30898175, default 2048): 98304【Startセクタの指定】 Last sector, +sectors or +size{K,M,G,T,P} (98304-30898175, default 30898175): 13068304 【Endセクタの指定】 Created a new partition 2 of type 'Linux' and of size 6.2 GiB. Partition #2 contains a ext4 signature. Do you want to remove the signature? [Y]es/[N]o: N 【ext4は変化せずsignatureを削除する必要は無いのでNを選択】 Command (m for help): p 【変化後の状態確認】 Disk /dev/sda: 14.8 GiB, 15819866112 bytes, 30898176 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xb973c9fe Device Boot Start End Sectors Size Id Type /dev/sda1 8192 96663 88472 43.2M c W95 FAT32 (LBA) /dev/sda2 98304 13068304 12970001 6.2G 83 Linux 【6.2Gに変化している】 Command (m for help): w 【変更を書き込む】 The partition table has been altered. Calling ioctl() to re-read partition table. Re-reading the partition table failed.: Device or resource busy
これで、縮小作業は終わりです。念のため、作業したSDカードで起動してみましたが、無事、6.1Gに変化していることが確認できました。
$ ssh [email protected] ・・・略・・・ pi@raspberrypi:~ $ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 6.1G 4.0G 1.8G 69% / ・・・略・・・
4 ブロック数を指定したイメージのコピー
ここからの作業は、Macで行っています。
SDカードからイメージを作成するには、ddコマンドを使用しますが、最後まで全部コピーしてしまうと結局サイズが縮まらないので、ブロック数の指定をします。
書き込みスピードを上げるためにブロック数を1Mバイトとすることにして、セクタ(単位は512バイト)の最後が12970001でしたので、12970001 / 2048 = 6333.0083... ということで6334ブロックまで書くことにします。
Macに接続すると、SDカードは、/dev/disk3で認識されています。
$ df -h Filesystem Size Used Avail Capacity iused ifree %iused Mounted on ・・・略・・・ /dev/disk3s1 43Mi 22Mi 21Mi 51% 0 0 100% /Volumes/boot
ブロックサイズを指定したコピーは、以下のとおりです。(途中経過を確認したい場合は、CTRL+T)
$ sudo dd bs=1m if=/dev/rdisk3 of=./RPI.img count=6334 6334+0 records in 6334+0 records out 6641680384 bytes transferred in 79.723395 secs (83309051 bytes/sec)
出来上がったイメージファイルのサイズは、当然、約6G、zipで圧縮すると約2Gになってました。
$ ls -la RPI* -rw-r--r-- 1 root staff 6641680384 8 16 03:41 RPI.img -rw-r--r-- 1 sin staff 2060124736 8 16 03:53 RPI.img.zip
5 リストア
リストアは、8GのSDカードで試してみることにします。イメージが6Gちょいなので、書き込めるはずです。
Macに接続して、下記のとおりイメージを書き出します。(/dev/disk3で認識している前提です)
$ diskutil umountDisk /dev/disk3 【アンマウントしないとddで書き込めない】 $ sudo dd bs=1m if=./RPI.img of=/dev/rdisk3 【イメージのコピー】 $ touch /Volumes/boot/ssh 【SSHを許可】 $ diskutil eject /dev/disk3 【イジェクト】
なお、この状態で起動すると、SDカードの最大容量まで使用した状態とはなっていません。
$ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 6.1G 4.0G 1.8G 69% / ・・・略・・・
広げる場合は、以下のようになります。(コマンド出力は省略されています)
$ sudo fdisk /dev/mmcblk0 【現在の状態を確認】 Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 96663 88472 43.2M c W95 FAT32 (LBA) /dev/mmcblk0p2 98304 13068304 12970001 6.2G 83 Linux 【パーティション2を削除】 Command (m for help): d Partition number (1,2, default 2):2 Partition 2 has been deleted. 【パーティション2を作成】 Command (m for help): n Partition type p primary (1 primary, 0 extended, 3 free) e extended (container for logical partitions) Select (default p):p Using default response p. Partition number (2-4, default 2): First sector (2048-15546367, default 2048): 98304 Last sector, +sectors or +size{K,M,G,T,P} (98304-15546367, default 15546367): 15546367 Created a new partition 2 of type 'Linux' and of size 7.4 GiB. Partition #2 contains a ext4 signature. Do you want to remove the signature? [Y]es/[N]o: N 【状態確認】 Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 96663 88472 43.2M c W95 FAT32 (LBA) /dev/mmcblk0p2 98304 15546367 15448064 7.4G 83 Linux Command (m for help): w
パーティション変更後は、反映のために再起動が必要です。
ファイルシステムは以下のコマンドで拡張できます。resize2fsは、サイズを指定しないと、パーティションサイズのいっぱいまでディスクサイズを拡張します。
$ sudo resize2fs /dev/mmcblk0p2 resize2fs 1.43.4 (31-Jan-2017) Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 1 The filesystem on /dev/mmcblk0p2 is now 1931008 (4k) blocks long.
これで、SDカードいっぱいまで利用可能になています。
pi@raspberrypi:~ $ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 7.2G 4.0G 3.0G 58% / ・・・略・・・
6 最後に
今回作成したイメージは6G程度でSDへの読み書きは4分程度でした。恐らく16Gでの作業と比べると半分以下の時間でコピーなどが可能になっているでしょう。リストア後にパーティション等を広げる作業をしても、時間節約は大きいと思います。また、リストアも6G以上のSDカードであれば、サイズ不足で書き込み失敗となる心配も無いはずです。
すこし、ややこしいですが、一通り作業すると、ファイルシステムとパーティションの理解も少し深まるかも知れません。